﻿namespace EyeOpen.ViewModel.Silverlight
{
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Threading;
    using System.Windows;
    using System.Windows.Threading;

    /// <summary>
    /// Provides common functionality for ViewModel classes
    /// </summary>
    public abstract class ViewModelBase : INotifyPropertyChanged, INotifyDataErrorInfo
    {
        private readonly List<CommandStatus> commandStatusList = new List<CommandStatus>();

        public event PropertyChangedEventHandler PropertyChanged;

        public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;

        public abstract bool HasErrors
        {
            get;
        }

        public abstract IEnumerable GetErrors(string propertyName);

        protected virtual void OnPropertyChanged(string propertyName)
        {
            var handler = PropertyChanged;

            Dispatcher currentDisp = null;

            if (Deployment.Current != null)
            {
                currentDisp = Deployment.Current.Dispatcher;
            }

            if (currentDisp != null)
            {
                currentDisp.BeginInvoke((ThreadStart)(() => PropertyChanged(this, new PropertyChangedEventArgs(propertyName))));
            }
            else
            {
                handler(this, new PropertyChangedEventArgs(propertyName));
            }

            foreach (var commandStatusItem in commandStatusList)
            {
                if (commandStatusItem.CheckCanExecuteChanged(null))
                {
                    commandStatusItem.UpdateCanExecuteState();
                }
            }
        }

        protected virtual void OnErrorsChanged(string propertyName)
        {
            var handler = ErrorsChanged;

            if (handler != null)
            {
                handler(this, new DataErrorsChangedEventArgs(propertyName));
            }
        }

        internal void Register(CommandStatus commandStatus)
        {
            commandStatusList.Add(commandStatus);
        }
    }
}
